home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Personal Computer World 2009 February
/
PCWFEB09.iso
/
Software
/
Resources
/
Chat & Communication
/
Digsby build 37
/
digsby_setup.exe
/
lib
/
oscar
/
OscarSocket.pyo
(
.txt
)
< prev
next >
Wrap
Python Compiled Bytecode
|
2008-10-13
|
14KB
|
457 lines
# Source Generated with Decompyle++
# File: in.pyo (Python 2.5)
from __future__ import with_statement
import sys
import logging
import struct
import socket
import collections
import time
from threading import RLock
from traceback import print_exc
import hub
import common
import oscar
from oscar.Snactivator import Snactivator
from util import lock, unpack_named, Storage, to_hex, try_this, callsback, isgeneratormethod
log = logging.getLogger('oscar.sock')
from struct import pack, unpack
from common import netcall
def flap_sequence_number():
i = 1
while None:
yield i
i += 1
if i >= 32768:
i = 1
continue
continue
return None
class OscarSocket(common.socket):
flap_hdr_size = 6
snac_hdr_size = 10
id = 42
func_templ = '\n def %(name)s (self):\n print "%(name)s is not implemented!"\n print self.hdr\n print self.data\n '
def default_cb(self, *a, **kw):
log.debug_s('Socket ignoring (%s, %s)', a, kw)
def __repr__(self):
try:
return '<OscarSocket %r>' % (self._OscarSocket__oserver,)
except Exception:
return '<OscarSocket ??>'
def __init__(self, server, cookie = None, incoming = None, close = None, callback = None, bos = False):
common.socket.__init__(self)
if not callback:
pass
self.on_connect = self.default_cb
if not incoming:
pass
self.on_incoming = self.default_cb
if not close:
pass
self.on_close = self.default_cb
self.callbacks = collections.defaultdict(list)
self.cookie = cookie
self.rate_lock = RLock()
self.hdr = None
self.buf = ''
self.data = ''
self.seq = flap_sequence_number()
self.req = flap_sequence_number()
self.rate_classes = []
self.rates = { }
self.rate_lvl_incr = False
self.snactivate = self._send_snac
self.snactivator = None
self.bos = bos
self.set_terminator(self.flap_hdr_size)
log.info('oscar socket created, connecting to %s', server)
self._OscarSocket__oserver = server
self.connect(server, error = callback.error)
__init__ = callsback(__init__)
def handle_error(self, e = None):
if isinstance(e, socket.error):
if self.on_close is not None:
log.error('Socket error for %r, calling on_close (= %r): %r', self, self.on_close, e)
self.on_close(self)
else:
log.info('handle_error in %r but on_close is None' % self)
common.socket.handle_error(self, e)
def test_connection(self):
try:
self.send_flap(5)
except Exception:
e = None
print_exc()
if not self.on_close:
pass
self.default_cb(self)
def apply_rates(self, rate_classes, rate_groups):
if not self.rate_classes:
self.rate_classes = rate_classes
else:
for rates in rate_classes:
id = rates[0]
self.rate_classes[id - 1] = rates
self.rates.update(rate_groups)
if self.snactivator is None:
self.snactivator = Snactivator(self)
self.snactivator.start()
self.snactivate = self.snactivator.send_snac
apply_rates = lock(apply_rates)
def calc_rate_level(self, rate_class):
old_level = rate_class.current_level
window = rate_class.window
now = int(time.time())
time_diff = (now - rate_class.last_time) * 1000
new_level = min(int(((window - 1) * old_level + time_diff) / window), rate_class.max_level)
return (new_level, now)
def snac_rate_class(self, fam, sub, *a):
try:
return self.rate_classes[self.rates[(fam, sub)] - 1]
except KeyError:
return None
def _get_rate_lvls(self, rclass):
return (rclass.max_level, rclass.current_level, rclass.alert_level, rclass.clear_level, rclass.window)
def time_to_send(self, s):
fam = s[0]
sub = s[1]
rclass = self.snac_rate_class(fam, sub)
(ml, curl, al, clrl, w) = self._get_rate_lvls(rclass)
threshold = min(ml, al + (clrl - al) * 2)
self.rate_lock.__enter__()
try:
if (curl < al or self.rate_lvl_incr) and curl < threshold:
self.rate_lvl_incr = True
else:
self.rate_lvl_incr = False
return 0
finally:
pass
k = 500
step = ml / k
wait = w * step + curl
delta = rclass.last_time - int(time.time())
to_send = delta + wait / 1000
return max(0, to_send)
def handle_connect(self):
log.debug('connected')
def handle_close(self):
log.info('closed. calling on_close=%r', self.on_close)
if not self.on_close:
pass
self.default_cb(self)
self.close()
def handle_expt(self):
log.warning('oob data')
self.handle_close()
def collect_incoming_data(self, data):
pass
def set_terminator(self, term):
common.socket.set_terminator(self, term)
def found_terminator(self):
try:
if self.hdr is None:
self._lock.__enter__()
try:
self.hdr = unpack_named('!BBHH', 'id', 'chan', 'seq', 'size', self.buf)
self.buf = ''
if self.hdr.size == 0:
self.found_terminator()
else:
self.set_terminator(self.hdr.size)
finally:
pass
else:
try:
getattr(self, 'channel_%d' % self.hdr.chan, self.unknown_channel)()
except oscar.errors:
e = None
hub.get_instance().on_error(e)
except Exception:
log.critical('Error handling FLAP 0x%x (DATA: %s) ' % (self.hdr.seq, repr(self.data)))
raise
finally:
self._lock.__enter__()
try:
(self.hdr, self.data) = (None, '')
self.set_terminator(self.flap_hdr_size)
finally:
pass
except socket.error:
raise
except Exception:
e = None
log.critical('%r had a non-socket error', self)
print_exc()
finally:
if self.terminator == 0:
log.critical('terminator was 0, closing socket!')
self.handle_close()
def close(self):
del self.on_incoming
self.on_incoming = None
common.socket.close(self)
def close_when_done(self):
self.on_close = None
if self.snactivator:
self.snactivator.stop()
del self.snactivator
self.snactivator = None
try:
self.send_flap(4)
except socket.error:
(errno, desc) = None
if errno not in (9, 10054, 10057):
raise
except:
errno not in (9, 10054, 10057)
common.socket.close_when_done(self)
def send_flap(self, chan, data = ''):
log.debug_s('Sending FLAP on channel %d, data is < %r >', chan, data)
(None, None, netcall)((lambda : common.socket.push(self, pack('!BBHH', self.id, chan, self.seq.next(), len(data)) + data)))
def send_snac(self, fam, sub, data = '', priority = 5, req = False, cb = None, *args, **kwargs):
req_id = self.req.next()
if req:
for k, v in list(self.callbacks.iteritems()):
if not v:
self.callbacks.pop(k)
continue
self.callbacks[req_id].append((cb, args, kwargs))
self.snactivate((fam, sub, req_id, data), priority)
def _send_snac(self, .1, priority = None):
(fam, sub, req_id, data) = .1
server_version = getattr(self, 'server_snac_versions', { }).get(fam, None)
if server_version is None:
version = None
else:
my_version = getattr(getattr(oscar.snac, 'family_x%02x' % fam), 'version', None)
if my_version == server_version or my_version is None:
version = None
else:
version = my_version
flags = None if version is None else 32768
if version:
ver_tlv = oscar.util.tlv(1, 2, version)
ver_tlv = pack('!H', len(ver_tlv)) + ver_tlv
else:
ver_tlv = ''
log.debug('sending snac: fam=0x%02x, sub=0x%02x, req=0x%04x', fam, sub, req_id)
log.debug_s('\t\tdata=%r', data)
to_send = pack('!HHHI', fam, sub, flags, req_id) + ver_tlv + data
self.send_flap(2, to_send)
if (fam, sub) in self.rates:
rclass = self.snac_rate_class(fam, sub)
(rclass.current_level, rclass.last_time) = self.calc_rate_level(rclass)
clevel = rclass.current_level
i = sorted(list(self._get_rate_lvls(rclass)) + [
clevel]).index(clevel)
(hi, lo) = ('disconnect', 'limit', 'alert', 'clear', 'max')[i:i + 2]
if not hi == 'clear' and lo == 'max':
log.debug('current rate level is: %s < %d < %s', hi, clevel, lo)
def channel_1(self):
log.info('got channel 1 (new connection) flap')
to_send = pack('!I', 1)
if self.cookie is not None:
to_send += oscar.util.tlv(6, self.cookie)
self._lock.__enter__()
try:
self.cookie = None
finally:
pass
self.send_flap(1, to_send)
try:
if not self.on_connect:
pass
self.default_cb(self)
except StopIteration:
pass
del self.on_connect
self.on_connect = None
def channel_2(self):
hdr = unpack_named('!HHHI', 'fam', 'sub', 'flags', 'req', self.data[:self.snac_hdr_size])
data = self.data[self.snac_hdr_size:]
log.debug('got channel 2 (snac data) flap. fam=0x%02x, sub=0x%02x, req=0x%04x', hdr.fam, hdr.sub, hdr.req)
log.debug_s('\t\tdata=%r', data)
snac = Storage(hdr = hdr, data = data)
if snac.hdr.flags & 32768:
log.debug('got version data for snac, trimming')
snac_ver_fmt = (('tlvs_len', 'H'), ('tlvs', 'tlv_list_len', 'tlvs_len'))
(tlvs_len, ver, snac.data) = oscar.util.apply_format(snac_ver_fmt, snac.data)
if self.is_ignored(snac):
log.debug('Ignored snac: %r', snac)
return None
cbs = self.callbacks
try:
if snac.hdr.req in cbs:
call_later = []
for func, args, kwargs in cbs[snac.hdr.req]:
if snac.hdr.flags & 1:
call_later.append((func, args, kwargs))
if isgeneratormethod(func):
try:
func((self, snac) + args)
except StopIteration:
pass
except:
None<EXCEPTION MATCH>StopIteration
None<EXCEPTION MATCH>StopIteration
func(self, snac, *args, **kwargs)
self._lock.__enter__()
try:
if not call_later:
cbs.pop(snac.hdr.req)
else:
cbs[snac.hdr.req] = call_later
finally:
pass
elif self.on_incoming is None:
self.default_cb(self, snac)
elif isgeneratormethod(self.on_incoming):
try:
self.on_incoming((self, snac))
except StopIteration:
pass
except Exception:
print repr(snac)
raise
except:
None<EXCEPTION MATCH>StopIteration
None<EXCEPTION MATCH>StopIteration
self.on_incoming(self, snac)
except oscar.snac.SnacError:
e = None
(fam, _) = ()
(sub, _) = e.args[:2]
if (fam, sub) in self.ignored_errors:
log.error('SNAC error occured: %r', snac)
else:
hub.get_instance().on_error(e)
except:
(fam, sub) in self.ignored_errors
def is_ignored(self, snac):
if (snac.hdr.fam, snac.hdr.sub) in self.ignored_snacs:
return True
ignored_snacs = [
(1, 19)]
ignored_errors = [
(1, 13),
(21, 2),
(19, 1),
(21, 5)]
def channel_4(self):
log.info('got channel 4 (close connection) flap')
fmt = (('tlvs', 'tlv_dict'),)
(tlvs, data) = oscar.unpack(fmt, self.data)
None if (try_this,)((lambda : ord(tlvs[9][-1])), False) else self.default_cb(self)
del self.on_close
self.on_close = None
self.close_when_done()
def unknown_channel(self):
log.warning('Unknown channel for data: %r', self.data)